package adminorg;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import java.util.Date;
import java.util.TreeMap;

public class PeriodHelper implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = -6721852609406678504L;
	private DatabaseHelper dbHelp = null;
	private Object PeriodId = null; 
	private String Type = null;
	private String StartDay = null;
	private Date BegDate = null;
	private boolean PeriodView = true;
	private Integer StatQuant = null;
	private String Current = null;
	private String Code = null;
	private Date CloseDate = null;

	
	public TreeMap<String,Integer> DOWCompare = new TreeMap<String,Integer>();
	
	public PeriodHelper(DatabaseHelper dbHelp,Object PeriodId){
		this.dbHelp=dbHelp;
		this.PeriodId = new Object();
		this.PeriodId=PeriodId;
		try {
			this.Code=new String(dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "code").getValue().toString());
			this.Type=new String(dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "type").getValue().toString());
			this.StartDay = new String(dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "start_day").getValue().toString());
			this.BegDate = new Date();
			this.BegDate = (Date)dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "begdate").getValue();
			this.PeriodView = new Boolean((Boolean)dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "periodview").getValue());
			this.StatQuant = new Integer((Integer)dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "statquant").getValue());
			this.Current = new String(dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "current").getValue().toString());
			//this.CloseDate = new Date();
			this.CloseDate = (Date)dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "closedate").getValue();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		DOWCompare.clear();
		DOWCompare.put("MONDAY", GregorianCalendar.MONDAY);
		DOWCompare.put("TUESDAY", GregorianCalendar.TUESDAY);
		DOWCompare.put("WEDNESDAY", GregorianCalendar.WEDNESDAY);
		DOWCompare.put("THURSDAY", GregorianCalendar.THURSDAY);
		DOWCompare.put("FRIDAY", GregorianCalendar.FRIDAY);
		DOWCompare.put("SATURDAY", GregorianCalendar.SATURDAY);
		DOWCompare.put("SUNDAY", GregorianCalendar.SUNDAY);
		

	}
	
	public void setPeriodId(Object PeriodId){
		this.PeriodId = new Object();
		this.PeriodId=PeriodId;
		try {
			this.Code=new String(dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "code").getValue().toString());
			this.Type=new String(dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "type").getValue().toString());
			this.StartDay = new String(dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "start_day").getValue().toString());
			this.BegDate = new Date();
			this.BegDate = (Date)dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "begdate").getValue();
			this.PeriodView = new Boolean((Boolean)dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "periodview").getValue());
			this.StatQuant = new Integer((Integer)dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "periodview").getValue());
			this.Current = new String(dbHelp.getAPeriodPropsContainer().getContainerProperty(PeriodId, "current").getValue().toString());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public Date[] getWeekPeriod(GregorianCalendar CalcDate){
		if (CalcDate==null) return null;
		Date[] ResPeriod = new Date[2];
		CalcDate.setFirstDayOfWeek(GregorianCalendar.MONDAY);
		if (CalcDate.get(GregorianCalendar.DAY_OF_WEEK)<DOWCompare.get(StartDay)){
			CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -7);
		}
		CalcDate.setFirstDayOfWeek(GregorianCalendar.MONDAY);
//		CalcDate.set(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.MONDAY);
//		CalcDate.add(GregorianCalendar.DAY_OF_WEEK, DOWCompare.get(StartDay)-GregorianCalendar.MONDAY-1);
		CalcDate.add(GregorianCalendar.DAY_OF_WEEK, DOWCompare.get(StartDay)-CalcDate.get(GregorianCalendar.DAY_OF_WEEK));
		ResPeriod[0]= new Date(CalcDate.getTimeInMillis());
		CalcDate.add(GregorianCalendar.DAY_OF_WEEK, 6);
		ResPeriod[1]= new Date(CalcDate.getTimeInMillis());
		return ResPeriod;
	}
	
	public Date getWeekPeriodFirstDate(GregorianCalendar CalcDate){
		if (CalcDate==null) return null;
		CalcDate.setFirstDayOfWeek(GregorianCalendar.MONDAY);
		if (CalcDate.get(GregorianCalendar.DAY_OF_WEEK)<DOWCompare.get(StartDay)){
			CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -7);
		}
		CalcDate.setFirstDayOfWeek(GregorianCalendar.MONDAY);
//		CalcDate.set(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.MONDAY);
		CalcDate.add(GregorianCalendar.DAY_OF_WEEK, DOWCompare.get(StartDay)-CalcDate.get(GregorianCalendar.DAY_OF_WEEK));
		Date ResDate = new Date(CalcDate.getTimeInMillis());
		return ResDate;
	}
	
	public Date[] getMonthPeriod(GregorianCalendar CalcDate){
		if (CalcDate==null) return null;
		Date[] ResPeriod = new Date[2];
		if (CalcDate.get(GregorianCalendar.DAY_OF_MONTH)>=Integer.parseInt(StartDay)){
			CalcDate.set(GregorianCalendar.DAY_OF_MONTH, Integer.parseInt(StartDay));
		} else {
			CalcDate.add(GregorianCalendar.MONTH, -1);
			CalcDate.set(GregorianCalendar.DAY_OF_MONTH, Integer.parseInt(StartDay));
		}
		ResPeriod[0]= new Date(CalcDate.getTimeInMillis());
		CalcDate.add(GregorianCalendar.MONTH, 1);
		CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -1);
		ResPeriod[1]=new Date(CalcDate.getTimeInMillis());
		return ResPeriod;
	}
	
	public Date getMonthPeriodFirsDate(GregorianCalendar CalcDate){
		if (CalcDate==null) return null;
		if (CalcDate.get(GregorianCalendar.DAY_OF_MONTH)>=Integer.parseInt(StartDay)){
			CalcDate.set(GregorianCalendar.DAY_OF_MONTH, Integer.parseInt(StartDay));
		} else {
			CalcDate.add(GregorianCalendar.MONTH, -1);
			CalcDate.set(GregorianCalendar.DAY_OF_MONTH, Integer.parseInt(StartDay));
		}
		Date ResDate = new Date(CalcDate.getTimeInMillis());
		return ResDate;
	}
	
	public Date[] getQuartPeriod(GregorianCalendar CalcDate){
		if (CalcDate==null) return null;
		Date[] ResPeriod = new Date[2];
		if (CalcDate.get(GregorianCalendar.DAY_OF_MONTH)>=Integer.parseInt(StartDay)){
			CalcDate.set(GregorianCalendar.DAY_OF_MONTH, Integer.parseInt(StartDay));
		} else {
			CalcDate.add(GregorianCalendar.MONTH, -1);
			CalcDate.set(GregorianCalendar.DAY_OF_MONTH, Integer.parseInt(StartDay));
		}
		GregorianCalendar BeginDate = (GregorianCalendar)GregorianCalendar.getInstance();
		BeginDate.setTime(BegDate);
		int StartQM = new Integer(BeginDate.get(GregorianCalendar.MONTH));
		int CurrM =  new Integer(CalcDate.get(GregorianCalendar.MONTH));
		int Diff = new Integer(CurrM-StartQM);
		if (Diff==1||Diff==4||Diff==7||Diff==10) Diff=-1;
		if (Diff==2||Diff==5||Diff==8||Diff==11) Diff=-2;
		if (Diff==0||Diff==3||Diff==6||Diff==9) Diff=0;
		if (Diff==-1||Diff==-4||Diff==-7||Diff==-10) Diff=-2;
		if (Diff==-2||Diff==-5||Diff==-8||Diff==-11) Diff=-1;
		CalcDate.add(GregorianCalendar.MONTH, Diff);
		ResPeriod[0]= new Date(CalcDate.getTimeInMillis());
		CalcDate.add(GregorianCalendar.MONTH, 3);
		CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -1);
		ResPeriod[1]=new Date(CalcDate.getTimeInMillis());
		return ResPeriod;
	}
	
	public Date getQuartPeriodFirstDate(GregorianCalendar CalcDate){
		if (CalcDate==null) return null;
		if (CalcDate.get(GregorianCalendar.DAY_OF_MONTH)>=Integer.parseInt(StartDay)){
			CalcDate.set(GregorianCalendar.DAY_OF_MONTH, Integer.parseInt(StartDay));
		} else {
			CalcDate.add(GregorianCalendar.MONTH, -1);
			CalcDate.set(GregorianCalendar.DAY_OF_MONTH, Integer.parseInt(StartDay));
		}
		GregorianCalendar BeginDate = (GregorianCalendar)GregorianCalendar.getInstance();
		BeginDate.setTime(BegDate);
		int StartQM = new Integer(BeginDate.get(GregorianCalendar.MONTH));
		int CurrM =  new Integer(CalcDate.get(GregorianCalendar.MONTH));
		int Diff = new Integer(CurrM-StartQM);
		if (Diff==1||Diff==4||Diff==7||Diff==10) Diff=-1;
		if (Diff==2||Diff==5||Diff==8||Diff==11) Diff=-2;
		if (Diff==0||Diff==3||Diff==6||Diff==9) Diff=0;
		if (Diff==-1||Diff==-4||Diff==-7||Diff==-10) Diff=-2;
		if (Diff==-2||Diff==-5||Diff==-8||Diff==-11) Diff=-1;
		CalcDate.add(GregorianCalendar.MONTH, Diff);
		Date ResDate = new Date(CalcDate.getTimeInMillis());
		return ResDate;
	}
	
	public Date[] getCurrentPeriodByDate(Date CurrentDate){
		GregorianCalendar CalcDate = (GregorianCalendar)GregorianCalendar.getInstance();
		CalcDate.setTime(CurrentDate);
		if (Type.equals("WEEKLY")){
			return getWeekPeriod(CalcDate);
		}
		if (Type.equals("MONTHLY")){
			return getMonthPeriod(CalcDate);
		}
		if (Type.equals("QUARTERLY")){
			return getQuartPeriod(CalcDate);
		}
		return null;
	}
	
	public int getCurrentPeriodNumbByDate(Date CurrentDate){
		GregorianCalendar CalcDate = (GregorianCalendar)GregorianCalendar.getInstance();
		GregorianCalendar BeginDate = (GregorianCalendar)GregorianCalendar.getInstance();
		GregorianCalendar EndDate = (GregorianCalendar)GregorianCalendar.getInstance();
		EndDate.setTime(CurrentDate);
		BeginDate.setTime(BegDate);
		int i=1;
		if (Type.equals("WEEKLY")){
			CalcDate.setTime(getWeekPeriodFirstDate(BeginDate));
			while (EndDate.after(CalcDate)){
				CalcDate.add(GregorianCalendar.WEEK_OF_MONTH, 1);
				i++;
			}
		}
		if (Type.equals("MONTHLY")){
			CalcDate.setTime(getMonthPeriodFirsDate(BeginDate));
			while (EndDate.after(CalcDate)){
				CalcDate.add(GregorianCalendar.MONTH, 1);
				i++;
			}
		}
		if (Type.equals("QUARTERLY")){
			CalcDate.setTime(getQuartPeriodFirstDate(BeginDate));
			while (EndDate.after(CalcDate)){
				CalcDate.add(GregorianCalendar.WEEK_OF_MONTH, 1);
				i++;
			}
		}
		return i; 		
	}
	
	public TreeMap<Date,String> getLastPeriodFromCurrent(Date CurrentDate){
		
		
		return null;		
	}
	
	public String getStringPeriod(Date D1,Date D2){
		String Res ="";
		SimpleDateFormat df =
			    new SimpleDateFormat("dd.MM.yyyy");
		String C1 = df.format(D1);
		String C2 = df.format(D2);
		if (!C1.substring(6, 10).equals(C2.substring(6, 10))) Res=C1.concat("-").concat(C2);
		else if (!C1.substring(3, 5).equals(C2.substring(3, 5))) Res=C1.substring(0, 5).concat("-").concat(C2);
		else Res=C1.substring(0, 3).concat("-").concat(C2);
		return Res;
	}
	
	public String getCurrent(){
		return this.Current;
	}
	
	public String getPeriod(){
		return this.Code;
	}
	
	public boolean getPeriodView(){
		return this.PeriodView;
	}
	
	public int getStatQuant(){
		return this.StatQuant;
	}
	
	public Date getCloseDate(){
		return TruncDate(this.CloseDate);
	}
	
	public Object getId(){
		return this.PeriodId;
	}
	
	public Date TruncDate(Date D){
		if (D==null) return null;
 		GregorianCalendar GC = (GregorianCalendar)GregorianCalendar.getInstance();
		GC.setTime(D);
		GC.set(GregorianCalendar.HOUR_OF_DAY, 10);
		GC.set(GregorianCalendar.MINUTE, 0);
		GC.set(GregorianCalendar.SECOND, 0);
		GC.set(GregorianCalendar.MILLISECOND, 0);
		return GC.getTime();
	}
	
	public GregorianCalendar TruncDate(GregorianCalendar GC){
		GC.set(GregorianCalendar.HOUR_OF_DAY, 10);
		GC.set(GregorianCalendar.MINUTE, 0);
		GC.set(GregorianCalendar.SECOND, 0);
		GC.set(GregorianCalendar.MILLISECOND, 0);
		return GC;
	}
	
	public TreeMap<Integer,Period> getLastPeriods(Date LastDate){
		Date CalcDate = LastDate;
		TreeMap<Integer,Period> LastPeriods = new TreeMap<Integer,Period>();
		int PeriodNumb = getCurrentPeriodNumbByDate(CalcDate);
		Date[] PeriodDate = new Date[2];
		GregorianCalendar CalcDateC = (GregorianCalendar)GregorianCalendar.getInstance();
		CalcDateC.setTime(CalcDate);
		CalcDateC = TruncDate(CalcDateC);
			for (int i=this.StatQuant;i>0;i--){
				PeriodDate = getCurrentPeriodByDate(CalcDate);				
				Period P = new Period(PeriodNumb,PeriodDate[0],PeriodDate[1],getStringPeriod(PeriodDate[0],PeriodDate[1]));
				LastPeriods.put(i, P);
				if( PeriodDate[0].before(BegDate)) break;
				if (Type.equals("WEEKLY")){
					CalcDateC.add(GregorianCalendar.DAY_OF_MONTH, -7);
				}
				if (Type.equals("MONTHLY")){
					CalcDateC.add(GregorianCalendar.MONTH, -1);
				}
				if (Type.equals("QUARTERLY")){
					CalcDateC.add(GregorianCalendar.MONTH, -3);
				}
				CalcDate = CalcDateC.getTime();
			}
		return LastPeriods;		
	}
	
	
	public TreeMap<Integer,Date> getLastPeriodsD(Date LastDate){
		Date CalcDate = LastDate;
		TreeMap<Integer,Date> LastPeriods = new TreeMap<Integer,Date>();
		GregorianCalendar CalcDateC = (GregorianCalendar)GregorianCalendar.getInstance();
		CalcDateC.setTime(CalcDate);
		CalcDateC = TruncDate(CalcDateC);
			for (int i=this.StatQuant;i>0;i--){		
				LastPeriods.put(i,CalcDateC.getTime());
				if( CalcDateC.getTime().before(BegDate)) break;
				CalcDateC.add(GregorianCalendar.DAY_OF_MONTH, -1);
			}
		return LastPeriods;		
	}
	
	public Date getCalculatedDate(Date CurrentDate){
		GregorianCalendar CalcDate = (GregorianCalendar)GregorianCalendar.getInstance(); 
		CalcDate.setTime(CurrentDate);
		CalcDate = TruncDate(CalcDate);
		if (Current.equals("-1DAY")) CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -1);
		else if (Current.equals("-2DAY")) CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -2);
		else if (Current.equals("-3DAY")) CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -3);
		else if (Current.equals("-4DAY")) CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -4);
		else if (Current.equals("-5DAY")) CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -5);
		else if (Current.equals("-1WEEK")) CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -7);
		else if (Current.equals("-2WEEK")) CalcDate.add(GregorianCalendar.DAY_OF_MONTH, -14);
		else if (Current.equals("-1MONTH")) CalcDate.add(GregorianCalendar.MONTH, -1); 
		return CalcDate.getTime();	
	}
	

}
